package com.easylinkin.linkappapi.alarm.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.bases.redis.util.RedisUtil;
import com.easylinkin.linkappapi.alarm.constant.AlarmConstant.ProcessStatus;
import com.easylinkin.linkappapi.alarm.entity.*;
import com.easylinkin.linkappapi.alarm.mapper.AlarmMapper;
import com.easylinkin.linkappapi.alarm.mapper.AlarmNoticeMapper;
import com.easylinkin.linkappapi.alarm.service.AlarmNoticeService;
import com.easylinkin.linkappapi.alarm.service.AlarmService;
import com.easylinkin.linkappapi.asset.service.AssetRefDeviceService;
import com.easylinkin.linkappapi.common.model.RequestModel;
import com.easylinkin.linkappapi.common.service.CommonService;
import com.easylinkin.linkappapi.common.utils.DateUtil;
import com.easylinkin.linkappapi.common.utils.excel.ExcelConstant;
import com.easylinkin.linkappapi.common.utils.excel.ExcelTools;
import com.easylinkin.linkappapi.common.utils.io.OutputStreamUtil;
import com.easylinkin.linkappapi.config.entity.Config;
import com.easylinkin.linkappapi.config.service.ConfigService;
import com.easylinkin.linkappapi.device.constant.DeviceConstant.DeviceStatusEnum;
import com.easylinkin.linkappapi.device.constant.DeviceConstant.StatisticsTimeTypeEnum;
import com.easylinkin.linkappapi.device.entity.Device;
import com.easylinkin.linkappapi.device.entity.DevicePosition;
import com.easylinkin.linkappapi.device.entity.vo.DevicePositionVo;
import com.easylinkin.linkappapi.device.service.DevicePositionService;
import com.easylinkin.linkappapi.device.service.DeviceService;
import com.easylinkin.linkappapi.elasticsearch.entity.EsQuerymodel;
import com.easylinkin.linkappapi.inspection.entity.ElectricBox;
import com.easylinkin.linkappapi.inspection.service.ElectricBoxService;
import com.easylinkin.linkappapi.listener.AirMonitorListener;
import com.easylinkin.linkappapi.listener.AlarmListener;
import com.easylinkin.linkappapi.listener.DeviceAlarmListener;
import com.easylinkin.linkappapi.listener.DeviceMonitorListener;
import com.easylinkin.linkappapi.openapi.service.OpenApiDataVService;
import com.easylinkin.linkappapi.ruleengine.entity.RuleExecution;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import com.easylinkin.linkappapi.space.entity.LinkappSpace;
import com.easylinkin.linkappapi.space.service.LinkappAreaService;
import com.easylinkin.linkappapi.space.service.LinkappSpaceService;
import com.easylinkin.linkappapi.tenant.entity.LinkappTenant;
import com.easylinkin.linkappapi.tenant.sevice.LinkappTenantService;
import com.easylinkin.linkappapi.webcammanage.util.YYSHDateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.stream.Collectors;


/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author Tongjie
 * @since 2020-04-25
 */
@Service
@Slf4j
public class AlarmServiceImpl extends ServiceImpl<AlarmMapper, Alarm> implements AlarmService {

    @Value("${linkapp.openReceiving:true}")
    private Boolean openReceiving;
    /**
     * 日志记录对象
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(AlarmServiceImpl.class);

    @Resource
    private DeviceService deviceService;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private CommonService commonService;
    @Resource
    private AlarmNoticeService alarmNoticeService;
    @Resource
    private AssetRefDeviceService assetRefDeviceService;
    @Resource
    private AlarmNoticeMapper alarmNoticeMapper;
    @Resource
    private AlarmListener alarmListener;
    @Resource
    private DeviceAlarmListener deviceAlarmListener;
//    @Resource
//    private DeviceMapListener deviceMapListener;
    @Resource
    private DeviceMonitorListener deviceMonitorListener;
    @Resource
    private AirMonitorListener airMonitorListener;

    @Resource
    LinkappAreaService linkappAreaService;
    @Resource
    LinkappSpaceService linkappSpaceService;

    @Value("${server.port}")
    private Integer serverPort;

    @Resource
    private LinkappTenantService tenantService;


    @Resource
    LinkappUserContextProducer linkappUserContextProducer;

    @Resource
    private DevicePositionService appDevicePositionService;
    @Autowired
    private ConfigService configService;


    @Override
    public IPage<Alarm> getAlarmPage(Page page, Alarm alarm) {
        List<String> spacesIds = commonService.getCurrentUserSpaceIds();
        if (CollectionUtils.isEmpty(spacesIds)) {
            return page;
        }
//        租户id 过滤
        alarm.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        return baseMapper.getAlarms(page, alarm, spacesIds);
    }

    /**
     * 获取 20分钟以内的告警数据
     */
    @Override
    public List<Alarm> getRecentAlarms() {
        // 参考分页查询接口的数据权限过滤
        List<String> spacesIds = commonService.getCurrentUserSpaceIds();
        if (CollectionUtils.isEmpty(spacesIds)) {
            return new ArrayList<>();
        }

        // 租户id 过滤
        String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();

        // 计算20分钟前的时间
        Date twentyMinutesAgo = new Date(System.currentTimeMillis() - 20 * 60 * 1000);

        // 构建查询条件
        Alarm alarm = new Alarm();
        alarm.setTenantId(tenantId);

        return baseMapper.getRecentAlarms(alarm, spacesIds, twentyMinutesAgo);
    }

    @Override
    public IPage<Alarm> getAlarmPageGlobal(Page page, Alarm alarm) {
        return baseMapper.getAlarmsGlobal(page, alarm);
    }

    @Override
    public IPage<Alarm> getDistributionAlarmPage(Page page, Alarm alarm) {
        Assert.notNull(alarm, "alarm 为空");
        Assert.hasLength(alarm.getDistributionRoomId(), "getDistributionRoomId 为空");
        List<String> spacesIds = commonService.getCurrentUserSpaceIds();
        if (CollectionUtils.isEmpty(spacesIds)) {
            return page;
        }
//        租户id 过滤
        alarm.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        return baseMapper.getDistributionAlarmPage(page, alarm, spacesIds);
    }


    @Override
    public IPage<Alarm> getAlarmPageByAsset(Page page, Alarm alarm) {
        List<String> deviceIds = assetRefDeviceService.getDeviceIdsByAssetId(alarm.getAssetId());
        if (null == deviceIds || CollectionUtils.isEmpty(deviceIds)) {
            return page;
        }
        return baseMapper.getAlarmPageByAsset(page, alarm, deviceIds);
    }

    @Override
    public Alarm getDetail(Alarm alarm) {
        return baseMapper.getDetail(alarm);
    }

    @Override
    public Alarm getDetail2(Alarm alarm) {
        return baseMapper.getDetail2(alarm);
    }

    @Override
    public Alarm getSourceJson(Alarm alarm) {
        QueryWrapper<Alarm> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("source_json");
        queryWrapper.eq("id", alarm.getId());
        return getOne(queryWrapper);
    }


    @Override
    public boolean ifLatestNoHandleAlarmExist(Alarm alarm) {
        alarm = baseMapper.getLatestAlarmByAlarm(alarm);
        return alarm != null && DateUtil.queryDateIsBeyondVal(alarm.getAlarmTime(), 24) && ProcessStatus.NOT_PROCESSED.getType().equals(alarm.getStatus());
    }

    @Override
    public int countAlarmByDeviceCodeAndStatus(String deviceCode, Integer status) {
        return baseMapper.countAlarmByDeviceCodeAndStatus(deviceCode, status);
    }

    @Override
    public void generateAlarm(Device device, RuleExecution ruleExecution, Date date) {

        LOGGER.info("generateAlarm检查产生告警方法被调用，ruleExecution 参数是：{}", JSONObject.toJSONString(ruleExecution));
        LOGGER.info("generateAlarm检查产生告警方法被调用，device参数是：{}", JSONObject.toJSONString(device));
        // 查询得的 未按照顺序sortNo 排序  需手动排下序
        Alarm alarm = new Alarm();
        alarm.setDeviceCode(device.getCode());
        alarm.setRuleEngineId(ruleExecution.getRuleEngineId());
        Object alarmData = redisUtil.get(ruleExecution.getRuleEngineId() + "@" + device.getCode());
        if (alarmData != null) {
            alarm.setAlarmData(alarmData.toString());
        }
        if (this.ifLatestNoHandleAlarmExist(alarm)) {
            LOGGER.info("告警日志中已经存在相同设备相同规则未处理的记录！");
            return;
        }

        LOGGER.info("检查是否产生告警满足条件，开始插入告警以及修改设备状态，设备是：{}", JSONObject.toJSONString(device));
        alarm.setDeviceCode(device.getCode());
        alarm.setDeviceName(device.getName());
//        由于保存时 date 会检查毫秒 mysql 会四舍五入存到秒，会导致后续根据时间找不到该条告警
        alarm.setAlarmTime(DateUtil.getDateFromYYYYMMDDHHmmss(DateUtil.getYYYYMMDDHHMMSSDate(date)));
        if (ObjectUtils.isNotEmpty(ruleExecution.getAlarmTemplate())) {
            alarm.setLevel(ruleExecution.getAlarmTemplate().getLevel());
            alarm.setContent(ruleExecution.getAlarmTemplate().getContent());
        }
        alarm.setStatus(ProcessStatus.NOT_PROCESSED.getType());
        if (ObjectUtils.isNotEmpty(ruleExecution.getRuleEngine())) {
            alarm.setTenantId(ruleExecution.getRuleEngine().getTenantId());
        }
        alarm.setSourceJson(device.getSourceJson());
        save(alarm);
        alarmListenSendNotice(alarm);

        //        修改设备状态为告警 状态
        UpdateWrapper updateWrapper = new UpdateWrapper();
        updateWrapper.eq("code", device.getCode());
        updateWrapper.set("status", DeviceStatusEnum.ALARM.getType());
        deviceService.update(updateWrapper);

        alarmListenSendNotice(alarm);

        if (ObjectUtils.isEmpty(ruleExecution.getAlarmTemplateId())) {
            return;
        }
        //List<AlarmNotice> alarmNotices = alarmNoticeMapper.getWaitInsertAlarmNotices(ruleExecution, device);
        //20220819变更逻辑，查询通知用户的通知（租户下的用户）
        List<AlarmNotice>  alarmNotices = alarmNoticeMapper.getWaitInsertAlarmNoticesTenant(ruleExecution,device);
        alarmNotices.forEach(alarmNotice -> {
            alarmNotice.setRuleEngineId(ruleExecution.getRuleEngineId());
//            change by tongjie 2021-7-15 chenjunjie需求告警提示短信内容优化
            alarmNotice.setDeviceType(alarmNotice.getDeviceType() + "(" + alarmNotice.getDeviceName() + ")");
        });
        alarmNoticeService.noticeAndSaveAlarmNotices(alarmNotices,device,alarm);
    }

    @Async
    public void alarmListenSendNotice(Alarm alarm) {
        alarmListener.sendNotice(alarm);
//        deviceMapListener.sendNotice(alarm);
        deviceAlarmListener.sendNotice(alarm);
        Device oneByDeviceCode = deviceService.findOneByDeviceCode(alarm.getDeviceCode());
        deviceMonitorListener.sendNotice(oneByDeviceCode);
        airMonitorListener.send(oneByDeviceCode);

    }


    @Override
    public List<Map> getAlarmStatisticsByRule(Alarm alarm) {
        alarm.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        return baseMapper.getAlarmStatisticsByRule(alarm);
    }

    @Override
    public List<AlarmStatistic> getAlarmStatisticsByStatus(Alarm alarm) {

        String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
        List<String> spacesIds = commonService.getCurrentUserSpaceIds();
        if (CollectionUtils.isEmpty(spacesIds)) {
            return new ArrayList<>();
        }
        List<AlarmStatistic> alarmStatisticsList = baseMapper.getAlarmStatisticsByStatus(alarm, tenantId, spacesIds);

        //2021-11-18确定查询最近7天的数据，统计区间无数据的话填充0
        List<AlarmStatistic> alarmStatisticsResult = fillAlarmStatistics(alarmStatisticsList, tenantId, alarm.getStatus());

        return alarmStatisticsResult;
    }

    @Override
    public List<AlarmStatistic> getAlarmStatisticsByStatus2(Alarm alarm) {
        String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
//        List<String> spacesIds = commonService.getCurrentUserSpaceIds();
//        if (CollectionUtils.isEmpty(spacesIds)) {
//            return new ArrayList<>();
//        }
        List<String> spacesIds = null;
        List<AlarmStatistic> alarmStatisticsList = baseMapper.getAlarmStatisticsByStatus2(alarm, tenantId, spacesIds);
        //2021-11-18确定查询最近7天的数据，统计区间无数据的话填充0
        List<AlarmStatistic> alarmStatisticsResult = fillAlarmStatistics(alarmStatisticsList, tenantId, alarm.getStatus());
        return alarmStatisticsResult;
    }


    private List<AlarmStatistic> fillAlarmStatistics(List<AlarmStatistic> alarmStatisticsList, String tenantId, Integer status) {
        List<AlarmStatistic> alarmStatisticsListResult = new ArrayList<>();
        //本周时间key   这里可以扩展前端传入截止时间，暂时默认截止时间是当前日期吧
        List<String> weekDateList = OpenApiDataVService.getTimeBetween(DateUtil.format(DateUtil.addDay(new Date(), -6), DateUtil.DATE_TIME_FORMAT_DAY),
                DateUtil.format(new Date(), DateUtil.DATE_TIME_FORMAT_DAY),
                DateUtil.DATE_TIME_FORMAT_DAY,
                Calendar.DAY_OF_YEAR);

        Collections.reverse(weekDateList);

        if (ObjectUtils.isEmpty(alarmStatisticsList)) {
            //无数据则全部填充默认值
            weekDateList.forEach(weekDate -> {
                alarmStatisticsListResult.add(new AlarmStatistic()
                        .setAlarmTime(weekDate)
                        .setSpaceId(null)
                        .setOneDayAddCount(0)
                        .setTenantId(tenantId)
                        .setStatus(status)
                );
            });
        } else {

            Map<String, List<AlarmStatistic>> alarmStatisticMap = alarmStatisticsList.stream().collect(Collectors.groupingBy(AlarmStatistic::getAlarmTime));
            weekDateList.forEach(weekDate -> {
                List<AlarmStatistic> alarmStatistics = alarmStatisticMap.get(weekDate);
                if (ObjectUtils.isEmpty(alarmStatistics)) {
                    alarmStatisticsListResult.add(new AlarmStatistic()
                            .setAlarmTime(weekDate)
                            .setSpaceId(null)
                            .setOneDayAddCount(0)
                            .setTenantId(tenantId)
                            .setStatus(status)
                    );
                } else {
                    alarmStatisticsListResult.add(alarmStatistics.get(0));
                }
            });
        }
        return alarmStatisticsListResult;
    }

    @Override
    public List<AlarmInfo> getAlarmStatisticsAudit(Alarm alarm) {
        if (StringUtils.isEmpty(alarm.getStatisticsTimeType())) {
            alarm.setStatisticsTimeType(StatisticsTimeTypeEnum.DAY.getType());
        }
        if (StringUtils.isEmpty(alarm.getQueryTimeEnd())) {
            alarm.setQueryTimeEnd(DateUtil.getYYYYMMDDDate(new Date()));
        }
        if (StringUtils.isEmpty(alarm.getQueryTimeStart())) {
            alarm.setQueryTimeStart(DateUtil.getYYYYMMDDDate(DateUtil.addDay(new Date(), -7)));
        }

        return baseMapper.getAlarmStatisticsAudit(alarm);
    }

    @Autowired
    private  ElectricBoxService electricBoxService;

    @Override
    public JSONObject getAlarmListForBigScreen() {
        //获取当前的打点设备
        Page page = new Page();
        page.setCurrent(1);
        page.setSize(-1);
        IPage<DevicePositionVo> devicePositionVoIPage = appDevicePositionService
            .selectPage(page, new DevicePositionVo());
        List<DevicePositionVo> records = devicePositionVoIPage.getRecords();
        List<String> deviceCodes = records.stream()
            .map(DevicePosition::getDeviceCode).collect(Collectors.toList());
        //找到配电箱的设备
        List<String> electricBoxCodes = records.stream().filter(
            item -> item.getDeviceTypeName() != null && item.getDeviceTypeName().equals("配电箱"))
            .map(DevicePosition::getDeviceCode).collect(Collectors.toList());
        if(CollectionUtil.isNotEmpty(deviceCodes)){
            List<String> param = new ArrayList<>();
            if(CollectionUtil.isNotEmpty(electricBoxCodes)){
                electricBoxCodes.forEach(new Consumer<String>() {
                    @Override
                    public void accept(String s) {
                        QueryWrapper<ElectricBox> queryWrapper = new QueryWrapper<>();
                        queryWrapper.eq("code_",s);
                        List<ElectricBox> list = electricBoxService.list(queryWrapper);
                        if(CollectionUtil.isNotEmpty(list)){
                            ElectricBox electricBox = list.get(0);
                            if(StringUtils.isNotBlank(electricBox.getMonitorDeviceCode())){
                                param.add(electricBox.getMonitorDeviceCode());
                            }
                        }
                    }
                });
            }
            if(deviceCodes.size()>electricBoxCodes.size()){
                deviceCodes.forEach(new Consumer<String>() {
                    @Override
                    public void accept(String s) {
                        if(!electricBoxCodes.contains(s)){
                            param.add(s);
                        }
                    }
                });
            }
            page.setSize(20);
            //最新的20条记录
            String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
            IPage<Alarm> alarmsForBigScreenPage = baseMapper
                .getAlarmsForBigScreenPageGlobal(page, param, tenantId);
            //统计今天得到告警数
            int sum = baseMapper.countAlarmByDeviceCodesGlobal(param,null, null,null, tenantId);
            int today = baseMapper.countAlarmByDeviceCodesGlobal(param,null, DateUtil.getTodayStartTime(),DateUtil.getTodayEndTime(), tenantId);
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("sum",sum);
            jsonObject.put("today",today);
            jsonObject.put("record",alarmsForBigScreenPage.getRecords());
            return jsonObject;
        }
        return null;
    }

    /**
     * 安全管理大屏查询告警信息
     * @return
     */
    @Override
    public Map<String, Object> countSecurityAlarmList() {
        Map<String, Object> map = new HashMap<>();
        //查询设置中的需要查询的设备类型
        Config config = configService.getOneByKeyAndTenantId("SECURITY_MONITORING_DEVICE_TYPES",null);
        String value = config.getValue();
        if (null != config && StringUtils.isNotBlank(value)){
            String[] strings = value.split(",");
            List<String> list = Arrays.asList(strings);
            //查询各分类的数量
            Page page = new Page();
            page.setCurrent(1);
            page.setSize(1);
            Alarm alarm = new Alarm();
            Device device = new Device();
            alarm.setDevice(device);
            //总告警数据
            AtomicInteger count = new AtomicInteger();
            list.forEach(l->{
                //查询数量
                alarm.setDeviceTypeName(l);
                IPage<Alarm> alarmIPage = this.getAlarmPage(page, alarm);
                map.put(l,alarmIPage.getTotal());
                count.addAndGet((int) alarmIPage.getTotal());
            });
            //查询总数量
            map.put("sum",count.get());

            //查询今天的数量
            alarm.setQueryTimeStart(DateUtil.format(DateUtil.getTodayStartTime(), DateUtil.DATE_TIME_FORMAT_DEFAULT));
            alarm.setQueryTimeEnd(DateUtil.format(DateUtil.getTodayEndTime(), DateUtil.DATE_TIME_FORMAT_DEFAULT));
            alarm.setDeviceTypeName(null);
            alarm.setDeviceTypeNames(list);
            IPage<Alarm> todayPage = this.getAlarmPage(page, alarm);
            map.put("today",todayPage.getTotal());
        }
        return map;
    }

    /**
     * 安全管理大屏查询告警信息列表
     * @param requestModel
     * @return
     */
    @Override
    public IPage<Alarm> getSecurityAlarmList(RequestModel<Alarm> requestModel) {
        Page page = requestModel.getPage();
        Alarm alarm = requestModel.getCustomQueryParams();
        Device device = new Device();
        alarm.setDevice(device);
        //查询设置中的需要查询的设备类型
        Config config = configService.getOneByKeyAndTenantId("SECURITY_MONITORING_DEVICE_TYPES",null);
        String value = config.getValue();
        if (null != config && StringUtils.isNotBlank(value)){
            String[] strings = value.split(",");
            List<String> list = Arrays.asList(strings);
            alarm.setDeviceTypeNames(list);
            IPage<Alarm> iPage = this.getAlarmPage(page, alarm);
            return iPage;
        }
        return null;
    }

    @Override
    public void getAlarmStatisticsAuditTask(Alarm alarm) {
        List<LinkappTenant> tenants = tenantService.selectLinkappTenantList(new LinkappTenant());
        for (LinkappTenant tenant : tenants) {
            List<AlarmInfo> alarmInfoList;
            alarm.setTenantId(tenant.getId());
            List<AlarmInfo> list = baseMapper.getAlarmStatisticsAudit(alarm);
            for (AlarmInfo alarmInfo : list) {
                List<String> spacelist = new ArrayList<>();
                spacelist.add(alarmInfo.getSpaceId());
                alarmInfoList = baseMapper.selectAlarmInfoList(alarmInfo, alarmInfo.getTenantId(), spacelist);
                if (alarmInfoList == null || alarmInfoList.isEmpty()) {
                    alarmInfo.setId(UUID.randomUUID().toString().replaceAll("-", ""));
                    baseMapper.insertAlarmInfo(alarmInfo);
                } else {
                    baseMapper.updateAlarmInfo(alarmInfo);
                }
            }
        }
    }

    @Override
    public AlarmAnalyzeStatistic statisticAlarmCountBySpace(EsQuerymodel esQuerymodel) {
        AlarmAnalyzeStatistic aas = new AlarmAnalyzeStatistic();

        //查询用户空间权限
        List<LinkappSpace> linkappSpaceList = linkappSpaceService.selectLinkappSpaceList(null);
        if (ObjectUtils.isEmpty(linkappSpaceList)) {
            return null;
        }
        List<String> spaceNameList = linkappSpaceList.stream().map(LinkappSpace::getSpaceName).collect(Collectors.toList());

        Map<String, Integer> sortMap = new LinkedHashMap<>();
        Map<String, AlarmAnalyzeStatistic.AlarmCount> dataMap = new LinkedHashMap<>();

        //未处理
        Alarm alarm = new Alarm()
                .setDevice(new Device().setAreaPath(esQuerymodel.getAreaPath()))
                .setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId())
                .setStatus(1);
        if (esQuerymodel.getCurrentBeginTime() != null && esQuerymodel.getCurrentEndTime() != null) {
            alarm.setQueryTimeStart(DateUtil.format(esQuerymodel.getCurrentBeginTime(), DateUtil.DATE_TIME_FORMAT_DEFAULT));
            alarm.setQueryTimeEnd(DateUtil.format(esQuerymodel.getCurrentEndTime(), DateUtil.DATE_TIME_FORMAT_DEFAULT));
        }
        List<AlarmCountByArea> alarmCountByAreas1 = baseMapper.countAlarmByAreaPathAndStatus(alarm);
        if (ObjectUtils.isEmpty(alarmCountByAreas1)) {
            aas.setSortData(null);
        } else {
            List<AlarmCountByArea> collect = alarmCountByAreas1.stream().sorted(Comparator.comparing(AlarmCountByArea::getAlarmCount).reversed()).collect(Collectors.toList());
            collect.forEach(e -> {
                if (spaceNameList.contains(e.getAreaName())) {
                    sortMap.put(e.getAreaName(), e.getAlarmCount());
                    dataMap.put(e.getAreaName(),
                            new AlarmAnalyzeStatistic.AlarmCount()
                                    .setUnHandlerCount(e.getAlarmCount() == null ? 0 : e.getAlarmCount())
                                    .setHandlerCount(0)
                    );
                }
            });
        }

        //已处理
        alarm.setStatus(2);
        List<AlarmCountByArea> alarmCountByAreas2 = baseMapper.countAlarmByAreaPathAndStatus(alarm);
        alarmCountByAreas2.forEach(e2 -> {
            if (spaceNameList.contains(e2.getAreaName())) {
                if (dataMap.containsKey(e2.getAreaName())) {
                    AlarmAnalyzeStatistic.AlarmCount alarmCount = dataMap.get(e2.getAreaName());
                    alarmCount.setHandlerCount(e2.getAlarmCount() == null ? 0 : e2.getAlarmCount());
                } else {
                    dataMap.put(e2.getAreaName(),
                            new AlarmAnalyzeStatistic.AlarmCount()
                                    .setHandlerCount(e2.getAlarmCount() == null ? 0 : e2.getAlarmCount())
                                    .setUnHandlerCount(0));
                }
            }
        });

        aas.setData(dataMap);
        aas.setSortData(sortMap);
        return aas;
    }

    @Override
    public AlarmAnalyzeStatistic statisticNormalUserAlarmCount(EsQuerymodel esQuerymodel) {
        AlarmAnalyzeStatistic aas = new AlarmAnalyzeStatistic();

        //查询用户空间权限
        List<LinkappSpace> linkappSpaceList = linkappSpaceService.selectLinkappSpaceList(null);
        if (ObjectUtils.isEmpty(linkappSpaceList)) {
            log.info("用户无空间权限");
            return null;
        }
        List<String> spaceNameList = linkappSpaceList.stream().map(LinkappSpace::getSpaceName).collect(Collectors.toList());
        if (!spaceNameList.contains(esQuerymodel.getAreaPath())) {
            log.info("无此空间区域权限");
            return null;
        }

        //未处理AlarmAnalyzeStatistic
        Alarm alarm = new Alarm()
                .setDevice(new Device().setAreaPath(esQuerymodel.getAreaPath()))
                .setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId())
                .setQueryTimeStart(DateUtil.format(DateUtil.addYear(new Date(), -1), DateUtil.DATE_TIME_FORMAT_DEFAULT))
                .setQueryTimeEnd(DateUtil.format(new Date(), DateUtil.DATE_TIME_FORMAT_DEFAULT));
        alarm.setStatus(1);
        List<AlarmCountByArea> unHandlerCountList = baseMapper.countAlarmByStatusAndAreaIds(alarm);
        Map<String, Integer> unHandlerCountMap = fillDateAndFormatData(unHandlerCountList, alarm.getQueryTimeStart(), alarm.getQueryTimeEnd());
        aas.setAlarmUnHandlerCount(unHandlerCountMap);

        //已处理
        alarm.setStatus(2);
        List<AlarmCountByArea> handlerCountList = baseMapper.countAlarmByStatusAndAreaIds(alarm);
        Map<String, Integer> handlerCountMap = fillDateAndFormatData(handlerCountList, alarm.getQueryTimeStart(), alarm.getQueryTimeEnd());
        aas.setAlarmHandlerCount(handlerCountMap);
        return aas;
    }

    private Map<String, Integer> fillDateAndFormatData(List<AlarmCountByArea> countList, String startTime, String endTime) {
        Map<String, Integer> dataMap = new LinkedHashMap<>();
        List<String> monthsList = YYSHDateUtil.getMonths(startTime, endTime);
        if (ObjectUtils.isEmpty(countList)) {
            for (String month :
                    monthsList) {
                dataMap.put(month, 0);
            }
        } else {
            Map<String, List<AlarmCountByArea>> collect = countList.stream().collect(Collectors.groupingBy(AlarmCountByArea::getMonth));
            for (String month :
                    monthsList) {
                if (collect.get(month) != null) {
                    dataMap.put(month, collect.get(month).get(0).getAlarmCount());
                } else {
                    dataMap.put(month, 0);
                }
            }
        }
        return dataMap;
    }

    @Override
    @Scheduled(cron = "0 10 12 * * ?")
    public void getAlarmStatisticsAuditTask() {
        try {
            if (!openReceiving) {
                LOGGER.info("openReceiving 为false");
                return ;
            }
            log.info("--------进入定时任务-------getAlarmStatisticsAuditTask-------");
            this.getAlarmStatisticsAuditTask(new Alarm());
            log.info("--------定时任务执行完成-------getAlarmStatisticsAuditTask-------");
        }catch (Exception e){
            log.error("--------定时任务执行异常-------getAlarmStatisticsAuditTask-------",e);
        }
    }

    @Override
    public Object getCurrentServicePort() {
//        return YamlUtils.get("application.yml", "server.port");
        return serverPort;
    }


    @Override
    public void exportData(Alarm alarm, HttpServletRequest request, HttpServletResponse response) {
        List<String> spacesIds = commonService.getCurrentUserSpaceIds();
        if (CollectionUtils.isEmpty(spacesIds)) {
            LOGGER.info("查询告警工单为空");
            return;
        }
//        租户id 过滤
        alarm.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        List<AlarmVo> result = baseMapper.getAlarmVos(alarm, spacesIds);
        String keyValue = "设备名称:deviceName,设备编号:deviceCode,设备类型:deviceTypeName,空间区域:deviceAreaPath,"
                + "告警规则:ruleEngineName,告警等级:level,告警内容:content,告警数据:alarmData,告警日志:sourceJson,告警时间:alarmTime,是否处理:processStatus,处理人:processUserName,"
                + "处理结果:processResult,是否误报:mistakeFlag,处理时间:processTime";
        String title = "告警工单导出表格";
        String fileName = title + ".xls";
        try {
            OutputStream outputStream = OutputStreamUtil
                    .getOutputStream(request, response, fileName);
            ExcelTools.exportExcel(outputStream, keyValue, result, ExcelConstant.XLS, title);
            response.flushBuffer();
            outputStream.close();
        } catch (IOException e) {
            LOGGER.error("excel导出失败", e);
            throw new RuntimeException("excel导出失败！IOException异常" + e.getMessage());
        } catch (Exception e) {
            LOGGER.error("excel导出失败", e);
            throw new RuntimeException("excel导出失败！" + e.getMessage());
        }

    }

    @Override
    public int countAlarm(Alarm alarm) {
        log.info("countAlarm被调用，参数是：{}", JSONObject.toJSONString(alarm));
        QueryWrapper<Alarm> qw = new QueryWrapper<>();
        if (ObjectUtils.isNotEmpty(alarm.getQueryTimeStart())) {
            qw.ge("alarm_time", alarm.getQueryTimeStart());
        }
        if (ObjectUtils.isNotEmpty(alarm.getQueryTimeEnd())) {
            qw.le("alarm_time", alarm.getQueryTimeEnd());
        }
        if (ObjectUtils.isNotEmpty(alarm.getStatus())) {
            qw.eq("status", alarm.getStatus());
        }
        return baseMapper.selectCount(qw);
    }
}
